Next.js is presently one of the fastest-growing web frameworks in terms of adoption. In addition to features like static site generation, server-side rendering, and file routing, the Next.js team continually adds new features to make building highly optimized and performant web applications super easy.
Despite the many benefits and features Next.js offers to developers, as with any framework, you might run into errors in your code during development. Next does a good job of logging helpful messages, but you might still find some errors hard to debug.
This article explores the causes and solutions of some common errors in Next.js, including:
Next.js hydration errorsDocument or window object errorBuild failure due to webpack errorsAPI and slug-related errorsError when importing modulesCORS error — Debugging Next.js API routesCatching all errors in your Next.js appLet’s jump right in.
1. Next.js hydration errorsOne common error you’re likely to encounter in both Next and React apps is the hydration error. Hydration errors result from a mismatch between server- and client-rendered markup and differences in component states.
Specifically, Next.js hydration errors arise when you wrap your components or HTML elements with an improper tag. A common example is when you have a p tag wrapping your divs, sections, or other elements.
The exact error message you’ll get is:
Hydration failed because the initial UI does not match what was rendered on the serverTo fix the error, you need to check the markup throughout your application and ensure that you’re not wrapping elements or custom components with improper tags.
For example, the following component will result in a Next.js hydration error because we wrapped the div element inside the paragraph:
import Image from 'next/image'export const ErrorComponent = ()=>{ return(Don't do this!
)}Rather, use the right “wrapper” elements — e.g. div, section, main, etc. — to wrap your content:
export const CorrectComponent = ()=>{ return( Do this instead)}Keep in mind that some third-party components, such as those from MUI, may use the
tag as a top-level element. In such cases, you’ll need to wrap the component inside something semantic to avoid the error, like a or .
Properly arranging your HTML will greatly reduce the likelihood of encountering the hydration error in your Next app, but it’s not the only cause. You can also encounter the error after importing and running certain packages, as we will explore in the next section.
2. Document or window object errorWhen you try to access the window object while the component is still mounting, Next.js will throw an error that the document or window is not defined. This error also occurs when you install and use a library that tries to access the window object before the component mounts.
Suppose that you have a home.js file in your Next.js application. Attempting to access the local storage will result in the window is not defined error:
const Home = () => { const saveSession = (event) => {window.sessionStorage.setItem("key", event.target.value) } return ( );};export default Home;This is the same with third-party libraries. For example, let’s say you installed the swiperjs package and the library then tries to access the window object internally. Using swiperjs as demonstrated in the code below will also result in the same error:
import { Swiper } from 'swiperjs'const Home = () => { return ( // Slides go here);};export default Home;This error occurs because Swiper is rendered before it can access the window object. To resolve this error, you need to execute the code that accesses the browser’s window object inside the useEffect() Hook. That way, the code only executes after the component has been mounted.
Here’s how you’d rewrite the first example for it to work:
const Home = () => { const saveSession = (event) => {useEffect(() => { window.sessionStorage.setItem("key", event.target.value)}) } return ( );};export default Home;If you’re using a library that accesses the window object, you need to load the library only after the component has been mounted. For example, this is how you’d load Swiper to avoid the error:
const Home = () => { const [domLoaded, setDomLoaded] = useState(false); useEffect(() => {setDomLoaded(true); }, []); return ( {domLoaded && ( Test )} );};export default Home;3. Build failure due to webpack errorsAfter running the next build command to build your Next.js application, you might get an error message stating that the build failed because of webpack errors:
Cannot read property 'asString' of undefined> Build error occurredError: > Build failed because of webpack errorsNext.js v11 and newer use webpack 5 by default. However, this error only occurs with webpack 4.
To resolve the issue, you need to enable webpack 5 in your Next.js application. You can do this by adding the following setting in next.config.js:
module.exports = { // Add this: future: {webpack5: true, },};4. API and slug-related errorsA large number of errors in Next.js are related to APIs and slugs. Next.js provides two APIs for data fetching — getStaticPaths and getServerSideProps. However, these functions can throw an error if not properly used.
Here’s an error you might often get with the getStaticProps API:
Error: getStaticPaths is required for dynamic SSG pages and is missing for '/productsPage/[slug]'You get this error when you render a page on the server side with the SSG feature, but fail to define the getStaticProps function in the page’s component.
This is because Next.js requires the getStaticPaths function to build server-side rendered or statically generated pages that use dynamic routes. So, the solution is simply to add a getStaticPaths() function to the page component for /pageName/[slug].
Over 200k developers use LogRocket to create better digital experiences Learn more →Let’s see an example. In a hypothetical ecommerce store, the /pageName/[slug] page could show the details of a particular product.
In that case, you can use the getStaticPaths function to retrieve a list of all the available product slugs from a database, then return the list to be used for the [slug] parameter:
export async function getStaticPaths() { const res = await fetch('http://localhost/path/to/products') const products = await res.json() const slugs = products.map(post => product.slug) return {paths: slugs.map((slug) => ({ params: { slug } })),fallback: false }}5. Error when importing modulesWhen importing modules into your Next.js application, you might run into the Module not found error:
Module not found: Can't resolve 'fs'This means that Next.js is unable to locate the module specified in the error message. If you’re using a local module, then you need to specify its correct path. But if it’s an npm or Yarn module, the error usually occurs because the module isn’t available on the client side.
One way to fix this issue is to ensure that all Node.js and server-related code is placed inside of the Next.js data-fetching APIs — getServerSideProps, getStaticPaths, or getStaticProps:
export function Home({ fileInfo }) { return ( {/* page content */} );}export default Home;export async function getServerSideProps(context) { const util = require('util'); const tring = util.format(1, 2, 3); return {props: { fileInfo,}, };}If that fails to resolve the issue, then you might want to cross-check that the letter casing of the file you’re attempting to import is correct. Here’s an example:
// components/MyComponent.jsexport default function MyComponent() { return Hello}When importing the above component, you need to use the exact letter case of the filename:
// pages/index.js// This will not workimport MyComponent from '../components/Mycomponent'// This will workimport MyComponent from '../components/MyComponent'Note that incorrect letter casing will only lead to Module not found errors in case-sensitive environments.
6. CORS error — Debugging Next.js API routesThe /pages/api directory is where you put all the files responsible for handling API requests, with the file name corresponding to the endpoint. Next.js then automatically maps these files to the /api/* URL, which you can access within the application via asynchronous API requests.
Once you deploy your app to the internet, the app will exist on a different origin. As a result, attempting to access the API endpoint will result in a CORS error as shown below:
Access to fetch at 'http://example.com/api/test' from origin 'http://localhost:3000' has been blocked by CORS policyTo fix the CORS issue, you need to use CORS to handle cross-origin requests. Start by installing cors:
npm install cors# ORyarn add corsOnce installation completes, you can import the library and use it to execute custom middleware just before the API’s response is received. Here’s an example where we set up the POST, GET, and HEAD methods for this endpoint:
// pages/api/test.jsimport Cors from "cors";const cors = Cors({ methods: ["POST", "GET", "HEAD"],});function middleware(req, res, fn) { return new Promise((resolve, reject) => {fn(req, res, (result) => { if (result instanceof Error) {return reject(result); } return resolve(result);}); });}export default async function runMiddleware(req, res) { await middleware(req, res, cors); // Other API logic res.json({ result: result });}With this code, we can make all four types of API requests to a different origin successfully without encountering the CORS error.
7. Catching all errors in your Next.js appWhen creating your Next.js application, it’s important to catch all errors and make sure each of them is handled. The best way to do this is at the component level using the try...catch syntax.
In the following example, if any error is encountered while fetching data from the API, we log the error, render the built-in error page, and pass in a 503 status code:
import fetch from "isomorphic-fetch"import Error from "next-error"const Home extends React.Component { static async getInitialProps() {let products = [];try {const resp = fetch("https://my-store.com")products = await resp.json()} catch(err) {console.log(err)}return { products } } render () {const { products } = this.propsif(products.length === 0) { return }return ( {products.map((product) => { {product.title} })} ) }}To learn more about catching and resolving errors in Next.js, check out our articles on testing and error handling patterns and troubleshooting a Next app with ESLint.
ConclusionNext.js is growing in popularity and usage. But as with any other technology, an application built with Next.js isn’t safe from errors and issues.
By reading up on common errors in Next.js, the causes of these errors, and their respective solutions — as we covered in this article — you can optimize your web app and ensure that it performs as expected.
LogRocket: Full visibility into production Next.js appsDebugging Next applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your Next.js app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.
The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.
Modernize how you debug your Next.js apps — start monitoring for free.